package cn.itsource.ymcc.mq.consumer;

import cn.itsource.ymcc.domain.PayOrder;
import cn.itsource.ymcc.dto.PayDto;
import cn.itsource.ymcc.service.IPayOrderService;
import cn.itsource.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;
@Component
@RocketMQMessageListener(
        consumerGroup="course-order-pay-consumer",
        topic="course-order-topic",
        selectorExpression="course-order-tag"
)
public class CourseOrderToPaycomsumer implements RocketMQListener<MessageExt> {
    @Autowired
    private IPayOrderService payOrderService;
    //消费消息
    /**
     * =============必须保证消费方消费消息的幂等性============
     * 1.拿到消息，检查消息不为空
     * 2.根据拿到的订单号，查询payOrder表，校验订单号对应的支付单是否已经存在
     * 2.1 有，说明已经消费过，直接签收消息--后面Mq就不会在推送此消息了
     * 2.2 没有，说明是第一次来消费这个消息，保存支付单 payOrder
     *
     * 扩展：作为RocketMq，消费方是否签收消息是通过是否有异常来判断的
     *    onMessage方法体：
     *      1.如果有异常，签收失败 -- 此消息会滞留在Mq中，下次还会再被消费--直到MQ 自动清理垃圾
     *      2.如果没有异常，签收成功  -- 消息就不再会被再次消费
     */
    @Override
    public void onMessage(MessageExt messageExt) {
    //消费消息 拿到消息，检查消息不为空
        byte[] body = messageExt.getBody();
        AssertUtil.isNotNull(body,"订单号不能为空");
        String jsonStr = new String(body, StandardCharsets.UTF_8);
        PayDto payDto = JSONObject.parseObject(jsonStr, PayDto.class);
        //2.根据拿到的订单号，查询payOrder表，校验订单号对应的支付单是否已经存在
        PayOrder payOrder = payOrderService.selectByOrderNo(payDto.getOrderNo());
        if(payOrder!=null){
            return;
        }
        //支付单 payOrder
        payOrder = new PayOrder();
        //直接赋值paydto 里面的内容
        BeanUtils.copyProperties(payDto,payOrder);
        payOrder.setCreateTime(new Date());
        //设置订单状态还是待支付
        payOrder.setPayStatus(PayOrder.STATE_WAIT_PAY);
        //保存支付单，后面会用
        payOrderService.insert(payOrder);

    }
}
